package org.tangerinejunction.imstats.util;

import java.util.Calendar;
import java.util.Date;

/**
 * A utility for describing a time range from a start date to an end date.
 * 
 * @author meganthorsen
 */
public class TimeRange 
{
	public static final char SEPARATOR = '.';
	public static final String REGEX = "\\.";
	public static final int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
	
	Calendar start;
	Calendar end;
	
	/**
	 * 
	 * @param start	the start time, in Calendar form
	 * @param end	the end time, in Calendar form
	 */
	public TimeRange(Calendar start, Calendar end)
	{
		this.start = start;
		this.end = end;
	}
	
	/**
	 * 
	 * @param startDate	the start time, in Date form
	 * @param endDate	the end time, in Date form
	 */
	public TimeRange(Date startDate, Date endDate)
	{
		start = Calendar.getInstance();
		start.set(1900+startDate.getYear(), startDate.getMonth(), startDate.getDate(), 0, 0, 0);
		end = Calendar.getInstance();
		end.set(1900+endDate.getYear(), endDate.getMonth(), endDate.getDate(), 23, 59, 59);
	}
	
	/**
	 * 
	 * @return	the beginning of the time range
	 */
	public Calendar getBeginning()
	{
		return start;
	}
	
	/**
	 * 
	 * @return	the end of the time range
	 */
	public Calendar getEnd()
	{
		return end;
	}
	
	public double getNumDays() {
	    long diff = end.getTimeInMillis() - start.getTimeInMillis();
	    return diff*1.0/MILLIS_IN_DAY;
	}
	
	/**
	 * 
	 * @param date	the date of interest
	 * @return		whether the date is inside this TimeRange
	 */
	public boolean contains(Calendar date)
	{
		if (start.compareTo(date) <= 0 && date.compareTo(end) < 0)
			return true;
		else
			return false;
	}
	
	public String toString()
	{
		return start.get(Calendar.DATE) + Character.toString(SEPARATOR) + (start.get(Calendar.MONTH)+1) + Character.toString(SEPARATOR) + start.get(Calendar.YEAR) + " to " + end.get(Calendar.DATE) + SEPARATOR + (end.get(Calendar.MONTH)+1) + SEPARATOR + end.get(Calendar.YEAR);
	}
	
	/**
	 * 
	 * @return	a String appropriate for chart labels
	 */
	public String toLabelString()
	{
		return start.get(Calendar.DATE) + Character.toString(SEPARATOR) + (start.get(Calendar.MONTH)+1) + Character.toString(SEPARATOR) + start.get(Calendar.YEAR);
	}
	
	/**
	 * 
	 * @param s	a String of interest
	 * @return	whether the String is in the right format to be a chart label
	 */
	public static boolean isLabelString(String s)
	{
		String[] vals = s.split(REGEX);
		return (vals.length == 3);
	}
	
	/**
	 * 
	 * @param labelString	the chart label to parse
	 * @param increment		the Increment associated with the label
	 * @return				the TimeRange represented by the label
	 */
	public static TimeRange parseLabelString(String labelString, Increment increment)
	{
		String[] startVals = labelString.split(REGEX);
		assert startVals.length == 3;
		Calendar start = Calendar.getInstance();
		start.set(Integer.parseInt(startVals[2]), Integer.parseInt(startVals[1])-1, Integer.parseInt(startVals[0]), 0, 0, 0);
		Calendar end = Calendar.getInstance();
		end.set(Integer.parseInt(startVals[2]) + increment.numYears, 
				Integer.parseInt(startVals[1])-1 + increment.numMonths, 
				Integer.parseInt(startVals[0]) + increment.numDays-1, 23, 59, 59);
		return new TimeRange(start, end);
	}

	/**
	 * 
	 * @param timeString	a full TimeRange string
	 * @return				the TimeRange represented by the String
	 */
	public static TimeRange parse(String timeString)
	{
		String[] times = timeString.split(" to ");
		assert times.length == 2;
		String[] startVals = times[0].split(REGEX);
		assert startVals.length == 3;
		String[] endVals = times[1].split(REGEX);
		assert endVals.length == 3;
		Calendar start = Calendar.getInstance();
		start.set(Integer.parseInt(startVals[0]), Integer.parseInt(startVals[1])-1, Integer.parseInt(startVals[2]), 0, 0, 0);
		Calendar end = Calendar.getInstance();
		end.set(Integer.parseInt(endVals[0]), Integer.parseInt(endVals[1])-1, Integer.parseInt(endVals[2]), 23, 59, 59);
		return new TimeRange(start, end);
	}
}
